package com.oa.ht.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mdp.core.err.BizException;
import com.mdp.core.service.BaseService;
import com.mdp.core.utils.BaseUtils;
import com.oa.ht.entity.*;
import com.oa.ht.mapper.ContractPaymentMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author maimeng-mdp code-gen
 * @since 2023年10月8日
 */
@Service
public class ContractPaymentService extends BaseService<ContractPaymentMapper, ContractPayment> {
    static Logger logger = LoggerFactory.getLogger(ContractPaymentService.class);

    /**
     * 自定义查询，支持多表关联
     *
     * @param page 分页条件
     * @param ew   一定要，并且必须加@Param("ew")注解
     * @param ext  如果xml中需要根据某些值进行特殊处理，可以通过这个进行传递，非必须，注解也可以不加
     * @return
     */
    public List<Map<String, Object>> selectListMapByWhere(IPage page, QueryWrapper ew, Map<String, Object> ext) {
        return baseMapper.selectListMapByWhere(page, ew, ext);
    }

    @Autowired
    ContractPaymentInvoiceService contractPaymentInvoiceService;
    @Autowired
    ContractConditionService contractConditionService;

    @Autowired
    ContractLogService contractLogService;

    @Autowired
    ContractCommonProcessApprovaService commonProcessApprovaService;

    @Autowired
    ContractCardService contractCardService;

    @Transactional
    public void add(ContractPaymentVo contractPayment) {
        ContractCondition contractCondition = new ContractCondition();
        contractCondition.setConditionId(contractPayment.getConditionId());
        contractCondition = contractConditionService.selectOneObject(contractCondition);
        if (contractCondition == null) {
            throw new BizException("付款条件为空");
        }
        if (!"0".equals(contractCondition.getDct())) {
            throw new BizException("请选择付款条件，而不是收款条件");
        }
        if ("2".equals(contractCondition.getConditionStatus())) {
            throw new BizException("该款项已完成付款，不能继续付款");
        }
        contractPayment.setPayStatus("0");
        contractPayment.setBizFlowState("0");
        this.insert(contractPayment);
        if (contractPayment.getInvoiceIds() != null && contractPayment.getInvoiceIds().size() > 0) {
            List<ContractPaymentInvoice> links = new ArrayList<>();
            for (String invoiceId : contractPayment.getInvoiceIds()) {
                ContractPaymentInvoice contractPaymentInvoice = new ContractPaymentInvoice();
                contractPaymentInvoice.setPaymentId(contractPayment.getId());
                contractPaymentInvoice.setHtId(contractPayment.getHtId());
                contractPaymentInvoice.setInvoiceId(invoiceId);
                links.add(contractPaymentInvoice);
            }
            contractPaymentInvoiceService.batchInsert(links);
        }
        this.contractConditionService.updateRequirePaymentAmountByConditionId(contractPayment.getConditionId());

        /**
         * 移动审批流中处理，审批通过再计算
         BigDecimal allFinishAmount=contractCondition.getFinishAmount();
         if(allFinishAmount==null||allFinishAmount.compareTo(BigDecimal.ZERO)==0){
         allFinishAmount=contractPayment.getPayAmount();
         }else{
         allFinishAmount=allFinishAmount.add(contractPayment.getPayAmount());
         }
         if(allFinishAmount!=null && allFinishAmount.compareTo(contractCondition.getConditionAmount())==0){
         ContractCondition contractConditionUpdate=new ContractCondition();
         contractConditionUpdate.setConditionId(contractCondition.getConditionId());
         contractConditionUpdate.setConditionStatus("2");
         contractConditionUpdate.setFinishAmount(allFinishAmount);
         contractConditionUpdate.setFinishDate(new Date());
         contractConditionService.updateSomeFieldByPk(contractConditionUpdate);
         }else{
         ContractCondition contractConditionUpdate=new ContractCondition();
         contractConditionUpdate.setConditionId(contractCondition.getConditionId());
         contractConditionUpdate.setFinishAmount(allFinishAmount);
         contractConditionService.updateSomeFieldByPk(contractConditionUpdate);
         }

         updateContractCardHtPayedAmount(contractPayment.getHtId());

         */
    }

    private void updateContractCardHtPayedAmount(String htId) {
//        super.update("com.oa.ht.entity.ContractCard.updateContractCardHtPayedAmount", htId);
        contractCardService.updateContractCardHtPayedAmount(htId);
    }

    @Transactional
    public void editContractPayment(ContractPaymentVo contractPayment) {
        this.updateSomeFieldByPk(contractPayment);
        ContractPaymentInvoice del = new ContractPaymentInvoice();
        del.setPaymentId(contractPayment.getId());
        contractPaymentInvoiceService.deleteByWhere(del);
        if (contractPayment.getInvoiceIds() != null && contractPayment.getInvoiceIds().size() > 0) {
            List<ContractPaymentInvoice> links = new ArrayList<>();
            for (String invoiceId : contractPayment.getInvoiceIds()) {
                ContractPaymentInvoice contractPaymentInvoice = new ContractPaymentInvoice();
                contractPaymentInvoice.setPaymentId(contractPayment.getId());
                contractPaymentInvoice.setHtId(contractPayment.getHtId());
                contractPaymentInvoice.setInvoiceId(invoiceId);
                links.add(contractPaymentInvoice);
            }
            contractPaymentInvoiceService.batchInsert(links);
        }
        this.contractConditionService.updateRequirePaymentAmountByConditionId(contractPayment.getConditionId());
    }

    public int deleteByPk(ContractPayment contractPayment) {
        int i = super.deleteByPk(contractPayment);
        this.contractConditionService.updateRequirePaymentAmountByConditionId(contractPayment.getConditionId());
        return i;
    }

    /**
     * 流程审批过程中回调该接口，更新业务数据
     * 如果发起流程时上送了restUrl，则无论流程中是否配置了监听器都会在流程发生以下事件时推送数据过来
     * eventName: PROCESS_STARTED 流程启动完成 全局
     * PROCESS_COMPLETED 流程正常结束 全局
     * PROCESS_CANCELLED 流程删除 全局
     * create 人工任务启动
     * complete 人工任务完成
     * assignment 人工任务分配给了具体的人
     * delete 人工任务被删除
     * TASK_COMPLETED_FORM_DATA_UPDATE 人工任务提交完成后，智能表单数据更新
     * <p>
     * 其中 create/complete/assignment/delete事件是需要在模型中人工节点上配置了委托代理表达式 ${taskBizCallListener}才会推送过来。
     * 在人工任务节点上配置 任务监听器  建议事件为 complete,其它assignment/create/complete/delete也可以，一般建议在complete,委托代理表达式 ${taskBizCallListener}
     *
     * @param flowVars {flowBranchId,agree,procInstId,startUserid,assignee,actId,taskName,mainTitle,branchId,bizKey,commentMsg,eventName,modelKey} 等
     * @return 如果tips.isOk==false，将影响流程提交
     **/
    @Transactional
    public void processApprova(Map<String, Object> flowVars) {
        String eventName = (String) flowVars.get("eventName");
        String agree = (String) flowVars.get("agree");
        String branchId = (String) flowVars.get("branchId");
        String paymentId = (String) flowVars.get("paymentId");//付款编号
        String htId = (String) flowVars.get("htId");//付款编号
        String bizKey = (String) flowVars.get("bizKey");
        if ("contract_payment_process_approva".equals(bizKey)) {
        } else {
            throw new BizException("不支持的业务,请上送业务编码【bizKey】参数");
        }

        if ("complete".equals(eventName)) {
            if ("1".equals(agree)) {
                this.updateFlowStateByProcInst(null, flowVars);
            } else {
                this.updateFlowStateByProcInst(null, flowVars);
            }
        } else {
            if ("PROCESS_STARTED".equals(eventName)) {
                if (StringUtils.isEmpty(paymentId)) {
                    throw new BizException("请上送付款编号-paymentId");
                }
                if (StringUtils.isEmpty(branchId)) {
                    throw new BizException("请上送branchId");
                }
                ContractPayment contractPayment = this.selectOneObject(new ContractPayment(paymentId));
                if (contractPayment == null) {
                    throw new BizException("没有找到对应付款单,付款编号为【" + paymentId + "】");
                } else {
                    if ("1".equals(contractPayment.getBizFlowState())) {
                        throw new BizException("该合同正在审批中，不能再发起审批");
                    }
                }

                flowVars.put("id", this.createKey("id"));
                flowVars.put("contractId", contractPayment.getHtId());
                flowVars.put("contractName", contractPayment.getHtName());
                ContractPayment update = new ContractPayment();
                update.setId(contractPayment.getId());
                update.setBizFlowState("1");
                update.setBizProcInstId((String) flowVars.get("procInstId"));
                this.updateSomeFieldByPk(update);
                flowVars.put("flowState", "1");
                flowVars.put("flowLastTime", new Date());
                commonProcessApprovaService.insert(BaseUtils.fromMap(flowVars, ContractCommonProcessApprova.class));
                this.contractLogService.addLog(contractPayment.getHtId(), (String) flowVars.get("startUserid"), (String) flowVars.get("startUsername"), "合同付款审核流程启动");
            } else if ("PROCESS_COMPLETED".equals(eventName)) {
                //流程表、订单表更新
                flowVars.put("flowEndTime", 1);//传入任意数值，表示flowEndTime需要修改
                if ("1".equals(agree)) {
                    flowVars.put("payStatus", "1");
                    this.updateFlowStateByProcInst("2", flowVars);
                    this.updateContractCardHtPayedAmount(htId);
                    ContractCondition contractConditionDb = this.contractConditionService.getConditionByPaymentId(paymentId);
                    this.contractConditionService.updateContractConditionPayFinishAmountAndStatus(contractConditionDb);
                    this.contractLogService.addLog(htId, (String) flowVars.get("startUserid"), (String) flowVars.get("startUsername"), "合同付款审批通过");
                } else {
                    this.contractLogService.addLog(htId, (String) flowVars.get("startUserid"), (String) flowVars.get("startUsername"), "合同付款审核流程已被拒绝");

                    this.updateFlowStateByProcInst("3", flowVars);
                }
            } else if ("PROCESS_CANCELLED".equals(eventName)) {
                //cancel为流程取消状态
                flowVars.put("flowEndTime", 1);//传入任意数值，表示flowEndTime需要修改
                this.contractLogService.addLog(htId, (String) flowVars.get("startUserid"), (String) flowVars.get("startUsername"), "合同付款审核流程取消");

                this.updateFlowStateByProcInst("4", flowVars);
            }
        }

    }

    /**
     * 0初始1审批中2审批通过3审批不通过4流程取消或者删除
     *
     * @param flowState 0初始1审批中2审批通过3审批不通过4流程取消或者删除
     * @param flowVars
     */
    public void updateFlowStateByProcInst(String flowState, Map<String, Object> flowVars) {
        flowVars.put("flowState", flowState);
        flowVars.put("bizFlowState", flowState);
        if ("1".equals(flowState)) {
            flowVars.put("bizProcInstId", flowVars.get("procInstId"));
        }
        commonProcessApprovaService.contractPaymentUpdateProcessApprova(flowVars);
    }
}

